home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / netroute / netroute.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-18  |  31.3 KB  |  1,191 lines

  1. /* 
  2.  * netroute.c --
  3.  *
  4.  *    User program to install routes to Sprite Hosts.  'route' is a misnomer
  5.  *    because the information also includes the hosts name and its
  6.  *    machine type.  Plus, the route is just a local address. 
  7.  *
  8.  * Copyright 1989 Regents of the University of California
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any purpose and without
  11.  * fee is hereby granted, provided that the above copyright
  12.  * notice appear in all copies.  The University of California
  13.  * makes no representations about the suitability of this
  14.  * software for any purpose.  It is provided "as is" without
  15.  * express or implied warranty.
  16.  */
  17.  
  18. #ifndef lint
  19. static char rcsid[] = "$Header: /sprite/src/cmds/netroute/RCS/netroute.c,v 1.21 92/06/23 12:08:36 jhh Exp $ SPRITE (Berkeley)";
  20. #endif not lint
  21.  
  22.  
  23. #include <sprite.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <bstring.h>
  27. #include <fs.h>
  28. #include <net.h>
  29. #include <host.h>
  30. #include <kernel/netTypes.h>
  31. #include <stdio.h>
  32. #include <option.h>
  33. #include <rpc.h>
  34. #include <kernel/rpcPacket.h>
  35. #include <sysStats.h>
  36. #include <sys/types.h>
  37. #include <sys/stat.h>
  38. #include <errno.h>
  39. #include <sys/time.h>
  40. #include <gate.h>
  41.  
  42. Net_NetworkType rankedInterfaceTypes[HOST_MAX_INTERFACES] =
  43.     { NET_ADDRESS_ETHER, NET_ADDRESS_FDDI, NET_ADDRESS_ULTRA };
  44.  
  45. static char *rankedInterfaceNames[HOST_MAX_INTERFACES] =
  46.     { "ether", "fddi", "ultra" };
  47.  
  48. static char *netTypeNames[NET_NUM_NETWORK_TYPES] = 
  49.     { "Ethernet", "UltraNet", "FDDI" };
  50.  
  51. #define NUM_NET_ADDRS    5
  52. static char *netAddressNames[NUM_NET_ADDRS] =
  53.     { "No Address", "Ethernet", "UltraNet", "FDDI", "Internet" };
  54.  
  55. static char *netProtocolNames[NET_MAX_PROTOCOLS] = 
  56.     { "raw", "inet" };
  57.  
  58. /*
  59.  * Parameters set by the command line
  60.  */
  61. char   *inputFilename = NULL;
  62. char   *hostName = NULL;
  63. int     first = -1;
  64. int     last = -1;
  65.  
  66. char   *gateFilename;
  67.  
  68. Boolean install = TRUE;
  69. int delete  = -1;
  70. Boolean print   = FALSE;
  71.  
  72. char   *favorName = NULL;
  73. char   *disfavorName = NULL;
  74.  
  75. char   *etherString = NULL;
  76. char   *ultraString = NULL;
  77. char   *fddiString = NULL;
  78.  
  79. Boolean verbose = FALSE;
  80. Boolean execute = FALSE;
  81. char   *machType;
  82. int     hostID = -1;
  83.  
  84. Option optionArray[] = {
  85.     {OPT_DOC, "\0", (Address)NULL, "  Hosts:"},
  86.     {OPT_STRING, "f", (Address)&inputFilename, 
  87.      "Specifies the host database file."},
  88.     {OPT_STRING, "h", (Address)&hostName, 
  89.      "Use Sprite host with given name or Sprite ID"},
  90.     {OPT_STRING, "g", (Address)&gateFilename,
  91.      "Specifies the gateway database file."},
  92.     {OPT_DOC, "\0", (Address)NULL, "  Actions:"},
  93.     {OPT_TRUE, "i", (Address)&install,
  94.      "Install route(s)."},
  95.     {OPT_INT, "d", (Address)&delete,
  96.      "Delete route."},
  97.     {OPT_TRUE, "p", (Address)&print,
  98.      "Print routes."},
  99.     {OPT_DOC, "\0", (Address)NULL, "  Interface favoring:"},
  100.     {OPT_STRING, "favor", (Address)&favorName,
  101.      "Try to install route(s) using this type of network interface."},
  102.     {OPT_STRING, "disfavor", (Address)&disfavorName,
  103.      "Try not to install route(s) using this type of network interface."},
  104.     {OPT_DOC, "\0", (Address)NULL, "\tCurrently (from first to last):"},
  105.     {OPT_DOC, "\0", (Address)NULL, "\t0. ether"},
  106.     {OPT_DOC, "\0", (Address)NULL, "\t1. fddi"},
  107.     {OPT_DOC, "\0", (Address)NULL, "\t2. ultra"},
  108.     {OPT_DOC, "\0", (Address)NULL, "  Address overriding:"},
  109.     {OPT_STRING, "ether", (Address)ðerString,
  110.      "Ethernet address for host. (ff:oo:oo:bb:aa:rr@aa.bb.cc.dd)"},
  111.     {OPT_STRING, "ultra", (Address)&ultraString,
  112.      "Ethernet address for host. (hh/ii@aa.bb.cc.dd)"},
  113.     {OPT_STRING, "fddi", (Address)&fddiString,
  114.      "Ethernet address for host. (qq:ww:ee:rr:tt:yy@aa.bb.cc.dd)"},
  115.     {OPT_DOC, "\0", (Address)NULL, "  Misc:"},
  116.     {OPT_TRUE, "v", (Address)&verbose, 
  117.      "Print out verbose messages"},
  118.     {OPT_TRUE, "n", (Address)&execute, 
  119.      "Do not execute commands.  Just print what would be done."},
  120.     {OPT_STRING, "m", (Address)&machType, 
  121.      "Machine type (sun2, spur, etc.)"},
  122. };
  123. int numOptions = Opt_Number(optionArray);
  124.  
  125. /*
  126.  * In kernel module net/netTypes.h
  127.  */
  128. #ifndef NET_NUM_SPRITE_HOSTS
  129. #define NET_NUM_SPRITE_HOSTS 200
  130. #endif
  131.  
  132. /*
  133.  * This is a hack. The subnet mask should be read in from a configuration 
  134.  * file. 
  135.  */
  136.  
  137. #define SUBNET_MASK 0xFFFFFF00
  138. #define SAME_SUBNET(addr1, addr2) \
  139.     (((addr1) & SUBNET_MASK) == ((addr2) & SUBNET_MASK))
  140.  
  141.  
  142. /*
  143.  *----------------------------------------------------------------------
  144.  *
  145.  * PrintRoutes --
  146.  *
  147.  *    Print the routes.
  148.  *
  149.  * Results:
  150.  *    FAILURE if there was a problem getting the routes, SUCCESS
  151.  *      otherwise.
  152.  *
  153.  * Side effects:
  154.  *    None.
  155.  *
  156.  *----------------------------------------------------------------------
  157.  */
  158. static ReturnStatus
  159. PrintRoutes()
  160. {
  161.     Net_Route    routes[NET_NUM_SPRITE_HOSTS];
  162.     Net_Route    *ptr;
  163.     ReturnStatus status;
  164.     int          i;
  165.     int          count;
  166.     char         buffer[64];
  167.  
  168.     status = Net_GetRoutes(-1, -1, sizeof(Net_Route), routes, &count);
  169.     if (status != SUCCESS) {
  170.     printf("Net_GetRoutes returned 0x%x: %s\n", status, 
  171.         Stat_GetMsg(status));
  172.     return FAILURE;
  173.     }
  174.  
  175.     for (i = 0; i < count; i++) {
  176.     ptr = &routes[i];
  177.     if (ptr->version != NET_ROUTE_VERSION) {
  178.         fprintf(stderr, "Route `%s' has invalid version number. ", 
  179.             ptr->desc);
  180.         fprintf(stderr, "It is %d, and should be %d.\n", ptr->version,
  181.             NET_ROUTE_VERSION);
  182.         continue;
  183.     }
  184.     if (!(ptr->flags & NET_FLAGS_VALID)) {
  185.         continue;
  186.     }
  187.     printf("%3d  %-20s %-8s\n", ptr->spriteID, ptr->hostname, 
  188.         ptr->machType);
  189.     printf("\t0x%08x %-5s %-8s %s -> ", ptr->routeID, 
  190.         netProtocolNames[ptr->protocol], netTypeNames[ptr->netType],
  191.         Net_AddrToString(&ptr->interAddress, buffer));
  192.     printf("%s\n", 
  193.         Net_AddrToString(&ptr->netAddress[NET_PROTO_RAW], buffer));
  194.     printf("\tPacket (%d, %d) RPC (%d, %d)\n", 
  195.         ptr->minPacket, ptr->maxPacket, ptr->minRpc, ptr->maxRpc);
  196.     }
  197.     return SUCCESS;
  198. }
  199.  
  200.  
  201.  
  202. /*
  203.  *----------------------------------------------------------------------
  204.  *
  205.  * OnSameNetworkType --
  206.  *
  207.  *      Determine if the two hosts are on the same type of network.
  208.  *
  209.  * Results:
  210.  *      TRUE if the hosts are on the same type of network, FALSE
  211.  *      otherwise.  If TRUE, then the given Host_NetInt pointers
  212.  *      will point to the corresponding Host_NetInt structures 
  213.  *      that enable the hosts to be on that network.  Those pointers
  214.  *      are only filled in if non-NULL.
  215.  *
  216.  * Side effects:
  217.  *    None.
  218.  *
  219.  *----------------------------------------------------------------------
  220.  */
  221. static Boolean
  222. OnSameNetworkType(type, srcPtr, srcIntPtrPtr, destPtr, destIntPtrPtr)
  223.     Net_NetworkType type;
  224.     Host_Entry      *srcPtr;
  225.     Host_NetInt     **srcIntPtrPtr;  /* (out) */
  226.     Host_Entry      *destPtr;
  227.     Host_NetInt     **destIntPtrPtr;  /* (out) */
  228. {
  229.     register int i;
  230.     register int j;
  231.  
  232.     for (i = 0; i < HOST_MAX_INTERFACES; i++) {
  233.     if (srcPtr->nets[i].netAddr.type == type) {
  234.         for (j = 0; j < HOST_MAX_INTERFACES; j++) {
  235.         if (destPtr->nets[j].netAddr.type == type) {
  236.             if (srcIntPtrPtr != (Host_NetInt **)NULL) {
  237.             *srcIntPtrPtr = &srcPtr->nets[i];
  238.             }
  239.             if (destIntPtrPtr != (Host_NetInt **)NULL) {
  240.             *destIntPtrPtr = &destPtr->nets[j];
  241.             }
  242.             return TRUE;
  243.         }
  244.         }
  245.     }
  246.     }
  247.     return FALSE;
  248. }
  249.  
  250.  
  251. /*
  252.  *----------------------------------------------------------------------
  253.  *
  254.  * InterfaceByType --
  255.  *
  256.  *      Find the network interface of the host that is of the
  257.  *      given type.
  258.  *
  259.  * Results:
  260.  *      The Host_NetInt structure of the given type, or NULL if
  261.  *      the host does not have a network interface of the given type.
  262.  *
  263.  * Side effects:
  264.  *    None.
  265.  *
  266.  *----------------------------------------------------------------------
  267.  */
  268. static Host_NetInt *
  269. InterfaceByType(hostPtr, netType)
  270.     Host_Entry      *hostPtr;
  271.     Net_AddressType netType;
  272. {
  273.     Host_NetInt *netIntPtr = NULL;
  274.     int i;
  275.  
  276.     if (hostPtr == (Host_Entry *)NULL) {
  277.     return netIntPtr;
  278.     }
  279.  
  280.     for (i = 0; i < HOST_MAX_INTERFACES; i++) {
  281.     netIntPtr = &hostPtr->nets[i];
  282.     if (netIntPtr->netAddr.type == netType) {
  283.         return netIntPtr;
  284.     }
  285.     }
  286.     return (Host_NetInt *)NULL;
  287. }
  288.  
  289. /*
  290.  *----------------------------------------------------------------------
  291.  *
  292.  * EstablishInternetRoute --
  293.  *
  294.  *      Establish an internet route between two hosts.
  295.  *
  296.  * Results:
  297.  *      SUCCESS iff the route was successfully established.  In this
  298.  *      case, the given route structure is filled in with the route
  299.  *      information.  Otherwise, FAILURE is returned.
  300.  *
  301.  * Side effects:
  302.  *    None.
  303.  *
  304.  *----------------------------------------------------------------------
  305.  */
  306. static ReturnStatus
  307. EstablishInternetRoute(srcHostPtr, destHostPtr, routePtr)
  308.     Host_Entry *srcHostPtr;
  309.     Host_Entry *destHostPtr;
  310.     Net_Route  *routePtr;
  311. {
  312.     Host_NetInt         *srcIntPtr;
  313.     Host_NetInt         *destIntPtr;
  314.     Gate_Entry          *gatePtr;
  315.     ReturnStatus        status;
  316.     static Boolean    initialized = FALSE;
  317.     static int        numGates;
  318. #define MAX_GATES    5
  319.     static Gate_Entry    gates[MAX_GATES];
  320.     Boolean        found;
  321.     int            i,j;
  322.  
  323.     if (!initialized) {
  324.     /*
  325.      * Read the gateway information.
  326.      */
  327.     status = Gate_Start();
  328.     if (status != SUCCESS) {
  329.         printf("netroute: couldn't set gate file.\n");
  330.         return FAILURE;
  331.     }
  332.     numGates = 0;
  333.     gatePtr = Gate_Next();
  334.     while (gatePtr != (Gate_Entry *)NULL) {
  335.         if (numGates == MAX_GATES) {
  336.         fprintf(stderr, "netroute: too many gateways\n");
  337.         return FAILURE;
  338.         }
  339.         gates[numGates] = *gatePtr;
  340.         gatePtr = Gate_Next();
  341.         numGates++;
  342.     }
  343.     Gate_End();
  344.     initialized = TRUE;
  345.     }
  346.  
  347.     /* 
  348.      * Go through the interfaces on the local host and find one that
  349.      * is connected to a gateway.
  350.      */
  351.     found = FALSE;
  352.     for (i = 0; i < HOST_MAX_INTERFACES; i++) {
  353.     srcIntPtr = InterfaceByType(srcHostPtr, rankedInterfaceTypes[i]);
  354.     if (srcIntPtr != NULL) {
  355.         for (j = 0; j < numGates; j++) {
  356.         gatePtr = &gates[j];
  357.         if (SAME_SUBNET(Net_NetToHostInt(srcIntPtr->inetAddr), 
  358.             Net_NetToHostInt(gatePtr->inetAddr))) {
  359.             found = TRUE;
  360.             goto endloop;
  361.         }
  362.         }
  363.     }
  364.     }
  365. endloop:
  366.     if (!found) {
  367.     if (verbose) {
  368.         printf("Couldn't find a gateway to use\n");
  369.     }
  370.     return FAILURE;
  371.     }
  372.  
  373.     /*
  374.      * Pick the best interface for the destination host. 
  375.      */
  376.     for (i = 0; i < HOST_MAX_INTERFACES; i++) {
  377.     destIntPtr = InterfaceByType(destHostPtr, rankedInterfaceTypes[i]);
  378.     if (destIntPtr != NULL) {
  379.         break;
  380.     }
  381.     }
  382.     if (destIntPtr == NULL) {
  383.     if (verbose) {
  384.         printf("Couldn't find an interface to use on the destination.\n");
  385.     }
  386.     return FAILURE;
  387.     }
  388.     routePtr->version = NET_ROUTE_VERSION;
  389.     routePtr->spriteID = destHostPtr->id;
  390.     routePtr->flags = NET_FLAGS_VALID;
  391.     strcpy(routePtr->hostname, destHostPtr->aliases[0]);
  392.     strcpy(routePtr->machType, destHostPtr->machType);
  393.     routePtr->minRpc = 0;
  394.     routePtr->maxRpc = RPC_MAX_SIZE;
  395.  
  396.     /*
  397.      * The protocol for a host across a gateway is INET.  To set up the
  398.      * route's addresses correctly, the INET address gets set to the internet
  399.      * address of the ethernet network interface of the destination host.
  400.      * The RAW address gets set to the ethernet address of the gateway.
  401.      * And the route's `interAddress' gets set to the network address of
  402.      * the interface to use.
  403.      * Yahoo!  Sheer simplicity.
  404.      */
  405.     routePtr->protocol = NET_PROTO_INET;
  406.     routePtr->netAddress[NET_PROTO_RAW] = gatePtr->netAddr;
  407.     routePtr->interAddress = srcIntPtr->netAddr;
  408.     status = Net_SetAddress(NET_ADDRESS_INET, (Address) &destIntPtr->inetAddr, 
  409.         &routePtr->netAddress[NET_PROTO_INET]);
  410.     if (status != SUCCESS) {
  411.     fprintf(stderr, "netroute: Net_SetAddress failed: %s\n",
  412.         Stat_GetMsg(status));
  413.     return FAILURE;
  414.     }
  415.     status = Net_InstallRoute(sizeof(Net_Route), routePtr);
  416.  
  417.     if (status != SUCCESS) {
  418.     fprintf(stderr, "netroute: Net_InstallRoute failed (0x%x): %s\n",
  419.         status, Stat_GetMsg(status));
  420.     return FAILURE;
  421.     } else {
  422.     if (verbose) {
  423.         printf("netroute: established internet %s route to %s.\n", 
  424.            netAddressNames[destIntPtr->netAddr.type], 
  425.            *destHostPtr->aliases);
  426.     }
  427.     }
  428.     return SUCCESS;
  429. }
  430.  
  431.  
  432. /*
  433.  *----------------------------------------------------------------------
  434.  *
  435.  * EstablishLocalRoute --
  436.  *
  437.  *      Establish an local route between two hosts.
  438.  *
  439.  * Results:
  440.  *      SUCCESS iff the route was successfully established.  In this
  441.  *      case, the given route structure is filled in with the route
  442.  *      information.  Otherwise, FAILURE is returned.
  443.  *
  444.  * Side effects:
  445.  *    None.
  446.  *
  447.  *----------------------------------------------------------------------
  448.  */
  449. static ReturnStatus
  450. EstablishLocalRoute(srcHostPtr, destHostPtr, routePtr)
  451.     Host_Entry *srcHostPtr;
  452.     Host_Entry *destHostPtr;
  453.     Net_Route  *routePtr;
  454. {
  455.     register int i;
  456.     Host_NetInt  *destIntPtr = NULL;
  457.     Host_NetInt  *srcIntPtr = NULL;
  458.     ReturnStatus result;
  459.     Boolean found;
  460.  
  461.     routePtr->version = NET_ROUTE_VERSION;
  462.     routePtr->spriteID = destHostPtr->id;
  463.     routePtr->flags = NET_FLAGS_VALID;
  464.     strcpy(routePtr->hostname, destHostPtr->aliases[0]);
  465.     strcpy(routePtr->machType, destHostPtr->machType);
  466.     routePtr->minRpc = 0;
  467.     routePtr->maxRpc = RPC_MAX_SIZE;
  468.  
  469.     /*
  470.      * See if the machines are connected to the same local network.
  471.      * If so, use it.
  472.      */
  473.     found = FALSE;
  474.     for (i = 0; i < HOST_MAX_INTERFACES; i++) {
  475.     if (OnSameNetworkType(rankedInterfaceTypes[i], srcHostPtr, &srcIntPtr, 
  476.                   destHostPtr, &destIntPtr)) {
  477.         if (SAME_SUBNET(Net_NetToHostInt(srcIntPtr->inetAddr), 
  478.             Net_NetToHostInt(destIntPtr->inetAddr))) {
  479.         found = TRUE;
  480.         break;
  481.         }
  482.     }
  483.     }
  484.     if (!found) {
  485.     return FAILURE;
  486.     }
  487.     if (verbose) {
  488.     printf("%s and %s are on the same %s \n",
  489.         srcHostPtr->name, destHostPtr->name, rankedInterfaceNames[i]);
  490.     }
  491.     /*
  492.      * Local machines use the RAW protocol.  The network address of the
  493.      * destination host is placed in the route's RAW protocol slot, and
  494.      * the network address of the source host is placed in the route's
  495.      * interface address slot.
  496.      */
  497.     routePtr->protocol = NET_PROTO_RAW;
  498.     routePtr->netAddress[NET_PROTO_RAW] = destIntPtr->netAddr;
  499.     routePtr->interAddress = srcIntPtr->netAddr;
  500.  
  501.     result = Net_InstallRoute(sizeof(Net_Route), routePtr);
  502.  
  503.     if (result != SUCCESS) {
  504.     fprintf(stderr, "netroute: Net_InstallRoute failed (0x%x): %s\n",
  505.         result, Stat_GetMsg(result));
  506.     return FAILURE;
  507.     } else {
  508.     if (verbose) {
  509.         printf("netroute: established raw %s route to %s.\n", 
  510.            netAddressNames[destIntPtr->netAddr.type], 
  511.            *destHostPtr->aliases);
  512.     }
  513.     return SUCCESS;
  514.     }
  515. }
  516.  
  517.  
  518. /*
  519.  *----------------------------------------------------------------------
  520.  *
  521.  * EstablishRoute --
  522.  *
  523.  *      Establish a route between two hosts.  If the two hosts
  524.  *      are across a gateway, then an internet route is established.
  525.  *      If they are not, then a local route is established.
  526.  *
  527.  * Results:
  528.  *      SUCCESS iff the route was successfully established.  In this
  529.  *      case, the given route structure is filled in with the route
  530.  *      information.  Otherwise, FAILURE is returned.
  531.  *
  532.  * Side effects:
  533.  *    None.
  534.  *
  535.  *----------------------------------------------------------------------
  536.  */
  537. static ReturnStatus
  538. EstablishRoute(srcHostPtr, destHostPtr, routePtr)
  539.     Host_Entry *srcHostPtr;
  540.     Host_Entry *destHostPtr;
  541.     Net_Route  *routePtr;
  542. {
  543.     ReturnStatus status;
  544.  
  545.     status = EstablishLocalRoute(srcHostPtr, destHostPtr, routePtr);
  546.     if (status == FAILURE) {
  547.     status = EstablishInternetRoute(srcHostPtr, destHostPtr, routePtr);
  548.     }
  549.     return status;
  550. }
  551.  
  552.  
  553. /*
  554.  *----------------------------------------------------------------------
  555.  *
  556.  * CopyHost --
  557.  *
  558.  *      Copy the contents of the source host structure into the
  559.  *      destination host structure.
  560.  *
  561.  * Results:
  562.  *      SUCCESS iff the copy was successful, FAILURE otherwise.
  563.  *
  564.  * Side effects:
  565.  *    None.
  566.  *
  567.  *----------------------------------------------------------------------
  568.  */
  569. static ReturnStatus
  570. CopyHost(srcHostPtr, destHostPtr)
  571.     Host_Entry *srcHostPtr;
  572.     Host_Entry *destHostPtr;
  573. {
  574.     bcopy((char *) srcHostPtr, (char *) destHostPtr, sizeof(Host_Entry));
  575.     destHostPtr->name = strdup(srcHostPtr->name);
  576.     destHostPtr->aliases = (char **)malloc(sizeof(char *) * 2);
  577.     *destHostPtr->aliases = strdup(*srcHostPtr->aliases);
  578.     *(destHostPtr->aliases + 1) = NULL;
  579.     return SUCCESS;
  580. }
  581.  
  582.  
  583. /*
  584.  *----------------------------------------------------------------------
  585.  *
  586.  * EstablishLocalHost --
  587.  *
  588.  *      Determine the Host_Entry for this host, i.e., the host that
  589.  *      the routes are established from.  This information is needed
  590.  *      before routes can be established to determine whether gateways
  591.  *      are crossed, etc.
  592.  *
  593.  * Results:
  594.  *      SUCCESS iff the local host could be found, FAILURE otherwise.
  595.  *      If SUCCESS, then the given Host_Entry structure is filled in
  596.  *      with the host information.
  597.  *
  598.  * Side effects:
  599.  *    None.
  600.  *
  601.  *----------------------------------------------------------------------
  602.  */
  603. static ReturnStatus
  604. EstablishLocalHost(hostPtr)
  605.     Host_Entry *hostPtr;
  606. {
  607.     ReturnStatus     result;
  608.     int              localID;
  609.     Host_Entry       *localPtr;
  610.     Net_Route        route;
  611.     int            i;
  612.     int            installed = 0;
  613.  
  614.     result = Proc_GetHostIDs(NULL, &localID);
  615.     if (result != SUCCESS) {
  616.     fprintf(stderr, "netroute: could not get this host's sprite ID.\n");
  617.     return FAILURE;
  618.     }
  619.     localPtr = Host_ByID(localID);
  620.     if (localPtr == (Host_Entry *)NULL) {
  621.     fprintf(stderr, "netroute: couldn't find local host by its ID (%d)\n",
  622.         localID);
  623.     return FAILURE;
  624.     }
  625.     if (verbose) {
  626.     printf("netroute: establishing routes from %s.\n", localPtr->name);
  627.     }
  628.     result = CopyHost(localPtr, hostPtr);
  629.     if (result != SUCCESS) {
  630.     return result;
  631.     }
  632.     localPtr = hostPtr;
  633.     /*
  634.      * This ensures that we know about ourself by giving the net module
  635.      * our internet address for each interface.
  636.      * Check in netRoute.c:Net_InstallRoute() for the details.
  637.      */
  638.     bzero((char *)&route, sizeof(Net_Route));
  639.     route.version = NET_ROUTE_VERSION;
  640.     route.spriteID = hostPtr->id;
  641.     route.flags = NET_FLAGS_VALID;
  642.     strcpy(route.hostname, hostPtr->aliases[0]);
  643.     strcpy(route.machType, hostPtr->machType);
  644.     route.minRpc = 0;
  645.     route.maxRpc = RPC_MAX_SIZE;
  646.     route.protocol = NET_PROTO_INET;
  647.     for (i = 0; i < HOST_MAX_INTERFACES; i++) {
  648.     if (hostPtr->nets[i].netAddr.type != NET_ADDRESS_NONE) {
  649.         route.netAddress[NET_PROTO_RAW] = hostPtr->nets[i].netAddr;
  650.         route.interAddress = hostPtr->nets[i].netAddr;
  651.         Net_SetAddress(NET_ADDRESS_INET, 
  652.         (Address) &hostPtr->nets[i].inetAddr, 
  653.         &route.netAddress[NET_PROTO_INET]);
  654.         result = Net_InstallRoute(sizeof(Net_Route), &route);
  655.         if (result != SUCCESS) {
  656.         fprintf(stderr, 
  657.             "netroute: Net_InstallRoute failed (0x%x): %s\n",
  658.             result, Stat_GetMsg(result));
  659.         } else {
  660.         installed++;
  661.         }
  662.     }
  663.     }
  664.     if (installed == 0) {
  665.     return FAILURE;
  666.     } 
  667.     return SUCCESS;
  668. }
  669.  
  670.  
  671. /*
  672.  *----------------------------------------------------------------------
  673.  *
  674.  * EstablishRoutesRange --
  675.  *
  676.  *      Establish routes to all hosts in a given range.  If the
  677.  *      endvalues of the range are both -1, then routes are established
  678.  *      to all hosts in the database file.
  679.  *
  680.  * Results:
  681.  *      SUCCESS iff the routes were established correctly, FAILURE
  682.  *      otherwise.
  683.  *
  684.  * Side effects:
  685.  *    None.
  686.  *
  687.  *----------------------------------------------------------------------
  688.  */
  689. static ReturnStatus
  690. EstablishRoutesRange(firstIDa, lastIDa)
  691.     int firstIDa;
  692.     int lastIDa;
  693. {
  694.     int result;
  695.     int count;
  696.     int firstID = firstIDa, lastID = lastIDa;
  697.     Host_Entry localHost;
  698.     Host_Entry *localPtr;
  699.     Host_Entry *hostPtr;
  700.     Net_Route route;
  701.     Net_Route oldRoutes[10];
  702.     int        i;
  703.  
  704.     localPtr = &localHost;
  705.     result = EstablishLocalHost(localPtr);
  706.     if (result != SUCCESS) {
  707.     fprintf(stderr, "netroute: couldn't establish address of this host\n");
  708.     return FAILURE;
  709.     }
  710.  
  711.     result = Host_Start();
  712.     if (result != SUCCESS) {
  713.     fprintf(stderr, "netroute: could not start host file.\n");
  714.     return FAILURE;
  715.     }
  716.     hostPtr = Host_Next();
  717.     while (hostPtr != (Host_Entry *)NULL) {
  718.     /*
  719.      * If the host is outside of the given range, skip it.
  720.      */
  721.     if ((firstID > 0) && (lastID > 0) && 
  722.         ((hostPtr->id < firstID) || (hostPtr->id > lastID))) {
  723.         hostPtr = Host_Next();
  724.         continue;
  725.     }
  726.     if (localPtr->id == hostPtr->id) {
  727.         hostPtr = Host_Next();
  728.         continue;
  729.     }
  730.     result = Net_GetRoutes(hostPtr->id, hostPtr->id, sizeof(oldRoutes), 
  731.                    oldRoutes, &count);
  732.     if (result != SUCCESS) {
  733.         count = 0;
  734.     }
  735.     route.userData = (ClientData) 0;
  736.     result = EstablishRoute(localPtr, hostPtr, &route);
  737.     if (result != SUCCESS) {
  738.         return result;
  739.     }
  740.     /*
  741.      * If we successfully established the route, then delete the
  742.      * previous ones. We only delete a previous route if its 
  743.      * userData is 0, meaning that it was installed by netroute
  744.      * from the host file. A userData value of 1 indicates that
  745.      * the route was installed by scratch (by the user) so we
  746.      * don't delete it lest the user get mad at us.
  747.      */
  748.     for (i = 0; i < count; i++) {
  749.         if (oldRoutes[i].userData == (ClientData) 0) {
  750.         if (verbose) {
  751.             printf("netroute: deleting previous route 0x%x\n", 
  752.             oldRoutes[i].routeID);
  753.         }
  754.         result = Net_DeleteRoute(oldRoutes[i].routeID);
  755.         if (result != SUCCESS) {
  756.             fprintf(stderr, "netroute: could not delete route 0x%x\n",
  757.             oldRoutes[i].routeID);
  758.             return FAILURE;
  759.         }
  760.         }
  761.     }
  762.     hostPtr = Host_Next();
  763.     }
  764.     return SUCCESS;
  765. }
  766.  
  767.  
  768. /*
  769.  *----------------------------------------------------------------------
  770.  *
  771.  * EstablishRouteScratch --
  772.  *
  773.  *      Establish a route to a host from scratch, i.e., from the
  774.  *      command line arguments.  
  775.  *
  776.  * Results:
  777.  *      SUCCESS iff the route was established correctly, FAILURE
  778.  *      otherwise.
  779.  *
  780.  * Side effects:
  781.  *    None.
  782.  *
  783.  *----------------------------------------------------------------------
  784.  */
  785. static ReturnStatus
  786. EstablishRouteScratch(spriteID)
  787.     int spriteID;
  788. {
  789.     int count;
  790.     ReturnStatus result;
  791.     Host_Entry tmpEntry;
  792.     Host_Entry *hostPtr;
  793.     Host_Entry *localPtr;
  794.     Host_Entry localHost;
  795.     Net_Route  route;
  796.  
  797.     /*
  798.      * Fill in the info for this host, and ensure that it knows
  799.      * about itself.
  800.      */
  801.     localPtr = &localHost;
  802.     result = EstablishLocalHost(localPtr);
  803.     if (result != SUCCESS) {
  804.     fprintf(stderr, "netroute: couldn't find info for local host.\n");
  805.     return FAILURE;
  806.     }
  807.     /*
  808.      * Put together the destination host from scratch.
  809.      */
  810.     hostPtr = &tmpEntry;
  811.     bzero((char *)hostPtr, sizeof(Host_Entry));
  812.     hostPtr->id = spriteID;
  813.     hostPtr->machType = machType;
  814.     hostPtr->name = strdup(hostName);
  815.     hostPtr->aliases = (char **)malloc(sizeof(char *) * 2);
  816.     *hostPtr->aliases = strdup(hostName);
  817.     *(hostPtr->aliases + 1) = NULL;
  818.     count = ManageAddressOverride(hostPtr);
  819.     if (count == 0) {
  820.     fprintf(stderr, "netroute: no addresses specified for installing a ");
  821.     fprintf(stderr, "route from scratch.\n");
  822.     return FAILURE;
  823.     }
  824.     route.userData = (ClientData) 1;
  825.     result = EstablishRoute(localPtr, hostPtr, &route);
  826.     return result;
  827. }
  828.  
  829.  
  830. /*
  831.  *----------------------------------------------------------------------
  832.  *
  833.  * DeleteRouteByID --
  834.  *
  835.  *      Delete the route denoted by its ID.
  836.  *
  837.  * Results:
  838.  *      SUCCESS iff the route was deleted correctly, FAILURE
  839.  *      otherwise.
  840.  *
  841.  * Side effects:
  842.  *    None.
  843.  *
  844.  *----------------------------------------------------------------------
  845.  */
  846. static ReturnStatus
  847. DeleteRouteByID(routeID)
  848.     int routeID;
  849. {
  850.     ReturnStatus status;
  851.  
  852.     if (verbose) {
  853.     printf("netroute: deleting route 0x%x/0x%x.\n", routeID,
  854.            routeID >> 16);
  855.     }
  856.     status = Net_DeleteRoute(routeID);
  857.     if (status != SUCCESS) {
  858.     printf("Net_DeleteRoute returned 0x%x: %s\n", status,
  859.            Stat_GetMsg(status));
  860.     return FAILURE;
  861.     }
  862.     return SUCCESS;
  863. }
  864.  
  865.  
  866. /*
  867.  *----------------------------------------------------------------------
  868.  *
  869.  * DeleteRoutesRange --
  870.  *
  871.  *      Delete the routes to the hosts whose Sprite IDs fall within
  872.  *      a given range.
  873.  *
  874.  * Results:
  875.  *      SUCCESS iff the routes were deleted correctly, FAILURE
  876.  *      otherwise.
  877.  *
  878.  * Side effects:
  879.  *    None.
  880.  *
  881.  *----------------------------------------------------------------------
  882.  */
  883. static ReturnStatus
  884. DeleteRoutesRange(firstID, lastID)
  885.     int firstID;
  886.     int lastID;
  887. {
  888.     int          count;
  889.     int          i;
  890.     ReturnStatus status;
  891.     Net_Route    routes[NET_NUM_SPRITE_HOSTS];
  892.  
  893.     status = Net_GetRoutes(firstID, lastID, sizeof(Net_Route), routes, &count);
  894.     if (status != SUCCESS) {
  895.     fprintf(stderr, "Net_GetRoutes returned 0x%x: %s\n", status, 
  896.         Stat_GetMsg(status));
  897.     return FAILURE;
  898.     }
  899.     for (i = 0; i < count; i++) {
  900.     status = Net_DeleteRoute(routes[i].routeID);
  901.     if (status != SUCCESS) {
  902.         printf("Net_DeleteRoute returned 0x%x: %s\n", status,
  903.            Stat_GetMsg(status));
  904.         return FAILURE;
  905.     }
  906.     }
  907.     return SUCCESS;
  908. }
  909.  
  910.  
  911. /*
  912.  *----------------------------------------------------------------------
  913.  *
  914.  * SplitOffInternetAddress --
  915.  *
  916.  *      Take a command line argument of the form
  917.  *      "net_address@internet_address", NULL the '@', and
  918.  *      return a pointer to the "internet_address".
  919.  *      
  920.  *
  921.  * Results:
  922.  *      A pointer to the "internet_address", or NULL if it could not
  923.  *      be found.
  924.  *
  925.  * Side effects:
  926.  *    None.
  927.  *
  928.  *----------------------------------------------------------------------
  929.  */
  930. static char *
  931. SplitOffInternetAddress(addrString)
  932.     register char *addrString;
  933. {
  934.     while (*addrString != '\0') {
  935.     if (*addrString == '@') {
  936.         *addrString  = '\0';
  937.         return (addrString + 1);
  938.     }
  939.     addrString++;
  940.     }
  941.     return NULL;
  942. }
  943.  
  944.  
  945. /*
  946.  *----------------------------------------------------------------------
  947.  *
  948.  * ManageAddressOverride --
  949.  *
  950.  *      Take the addresses given on the command line and convert
  951.  *      them into Host_NetInt structures for the given host.
  952.  *
  953.  * Results:
  954.  *      The number of network addresses converted from the command
  955.  *      line.
  956.  *      
  957.  *
  958.  * Side effects:
  959.  *    None.
  960.  *
  961.  *----------------------------------------------------------------------
  962.  */
  963. static int
  964. ManageAddressOverride(hostPtr)
  965.     Host_Entry *hostPtr;
  966. {
  967.     char *inetStr;
  968.     int index = 0;
  969.     Host_NetInt *netIntPtr;
  970.     ReturnStatus result;
  971.  
  972.     if (etherString != NULL) {
  973.     netIntPtr = &hostPtr->nets[index];
  974.     inetStr = SplitOffInternetAddress(etherString);
  975.     result = Net_StringToAddr(etherString, NET_ADDRESS_ETHER, 
  976.                      &netIntPtr->netAddr);
  977.     if (result != SUCCESS) {
  978.         fprintf(stderr, "netroute: couldn't convert %s to an ethernet ",
  979.             etherString);
  980.         fprintf(stderr, "address for host %d.\n", hostPtr->id);
  981.         return 0;
  982.     }
  983.     netIntPtr->inetAddr = Net_StringToInetAddr(inetStr);
  984.     index++;
  985.     }
  986.     if (ultraString != NULL) {
  987.     netIntPtr = &hostPtr->nets[index];
  988.     inetStr = SplitOffInternetAddress(ultraString);
  989.     result = Net_StringToAddr(ultraString, NET_ADDRESS_ULTRA, 
  990.                      &netIntPtr->netAddr);
  991.     if (result != SUCCESS) {
  992.         fprintf(stderr, "netroute: couldn't convert %s to an ultranet ",
  993.             ultraString);
  994.         fprintf(stderr, "address for host %d.\n", hostPtr->id);
  995.         return 0;
  996.     }
  997.     netIntPtr->inetAddr = Net_StringToInetAddr(inetStr);
  998.     index++;
  999.     }
  1000.     if (fddiString != NULL) {
  1001.     netIntPtr = &hostPtr->nets[index];
  1002.     inetStr = SplitOffInternetAddress(fddiString);
  1003.     result = Net_StringToAddr(fddiString, NET_ADDRESS_FDDI, 
  1004.                      &netIntPtr->netAddr);
  1005.     if (result != SUCCESS) {
  1006.         fprintf(stderr, "netroute: couldn't convert %s to an FDDI ",
  1007.             fddiString);
  1008.         fprintf(stderr, "address for host %d.\n", hostPtr->id);
  1009.         return 0;
  1010.     }
  1011.     netIntPtr->inetAddr = Net_StringToInetAddr(inetStr);
  1012.     index++;
  1013.     }
  1014.     return index;
  1015. }
  1016.  
  1017.  
  1018. /*
  1019.  *----------------------------------------------------------------------
  1020.  *
  1021.  * ManageFavorings --
  1022.  *
  1023.  *      Juggle the list of network types according to the favorings
  1024.  *      in the command line.  The program is compiled with a default
  1025.  *      list of network types that it will traverse when trying to
  1026.  *      establish routes to a host, and it will establish the first one
  1027.  *      that it can.  The user can change the list ordering
  1028.  *      using the command line to change this behavior.
  1029.  *
  1030.  * Results:
  1031.  *      None.
  1032.  *
  1033.  * Side effects:
  1034.  *    None.
  1035.  *
  1036.  *----------------------------------------------------------------------
  1037.  */
  1038. static void
  1039. ManageFavorings()
  1040. {
  1041.     register int    i;
  1042.     register int    j;
  1043.     register char   *ptr;
  1044.     Net_NetworkType type;
  1045.  
  1046.     if (favorName != NULL) {
  1047.     for (i = 0; i < HOST_MAX_INTERFACES; i++) {
  1048.         if (!strcmp(favorName, rankedInterfaceNames[i])) {
  1049.         ptr = rankedInterfaceNames[i];
  1050.         type = rankedInterfaceTypes[i];
  1051.         for (j = i - 1; j >= 0; j--) {
  1052.             rankedInterfaceNames[j + 1] = rankedInterfaceNames[j];
  1053.             rankedInterfaceTypes[j + 1] = rankedInterfaceTypes[j];
  1054.         }
  1055.         rankedInterfaceNames[0] = ptr;
  1056.         rankedInterfaceTypes[0] = type;
  1057.         break;
  1058.         }
  1059.     }
  1060.     }
  1061.     if (disfavorName != NULL) {
  1062.     for (i = 0; i < HOST_MAX_INTERFACES; i++) {
  1063.         if (!strcmp(disfavorName, rankedInterfaceNames[i])) {
  1064.         ptr = rankedInterfaceNames[i];
  1065.         type = rankedInterfaceTypes[i];
  1066.         for (j = i + 1; j < HOST_MAX_INTERFACES; j++) {
  1067.             rankedInterfaceNames[j - 1] = rankedInterfaceNames[j];
  1068.             rankedInterfaceTypes[j - 1] = rankedInterfaceTypes[j];
  1069.         }
  1070.         rankedInterfaceNames[HOST_MAX_INTERFACES - 1] = ptr;
  1071.         rankedInterfaceTypes[HOST_MAX_INTERFACES - 1] = type;
  1072.         break;
  1073.         }
  1074.     }
  1075.     }
  1076.     if (verbose) {
  1077.     printf("netroute: Interface Rankings: ");
  1078.     for (i = 0; i < HOST_MAX_INTERFACES; i++) {
  1079.         printf("%d. %s ", i, rankedInterfaceNames[i]);
  1080.     }
  1081.     printf("\n");
  1082.     }                   
  1083. }
  1084.  
  1085.  
  1086. /*
  1087.  *----------------------------------------------------------------------
  1088.  *
  1089.  * main --
  1090.  *
  1091.  *      Establish, delete, or print routes to specified hosts.
  1092.  *
  1093.  * Results:
  1094.  *      None.
  1095.  *
  1096.  * Side effects:
  1097.  *    None.
  1098.  *
  1099.  *----------------------------------------------------------------------
  1100.  */
  1101. int
  1102. main(argc, argv)
  1103.     int argc;
  1104.     char *argv[];
  1105. {
  1106.     ReturnStatus result;
  1107.     Host_Entry   *entryPtr;
  1108.  
  1109.     argc = Opt_Parse(argc, argv, optionArray, numOptions, 0);
  1110.     if (first < 0 && last > -1) {
  1111.     first = 0;
  1112.     }
  1113.     if (last < 0 && first > -1) {
  1114.     last = NET_NUM_SPRITE_HOSTS;
  1115.     }
  1116.     if (last < first) {
  1117.     fprintf(stderr, "netroute: `last' (%d) less than `first' (%d)\n", 
  1118.         last, first);
  1119.     exit(1);
  1120.     }
  1121.  
  1122.     if (print) {
  1123.     install = FALSE;
  1124.     }
  1125.     if (inputFilename != NULL) {
  1126.     Host_SetFile(inputFilename);
  1127.     result = Host_Start();
  1128.     if (result != SUCCESS) {
  1129.         fprintf(stderr, "netroute: could not open host file %s.\n",
  1130.             inputFilename);
  1131.         exit(1);
  1132.     }
  1133.     }
  1134.  
  1135.     if (hostName != NULL) {
  1136.     entryPtr = Host_ByName(hostName);
  1137.     if (entryPtr == (Host_Entry *)NULL) {
  1138.         hostID = atoi(hostName);
  1139.         entryPtr = Host_ByID(hostID);
  1140.         if (entryPtr == (Host_Entry *)NULL) {
  1141.         fprintf(stderr, "netroute: could not resolve host %s\n",
  1142.             hostName);
  1143.         exit(1);
  1144.         }
  1145.         hostName = strdup(entryPtr->name);
  1146.     } else {
  1147.         hostID = entryPtr->id;
  1148.     }
  1149.     }
  1150.  
  1151.     /*
  1152.      * If a host is specified, then it overrides a range.
  1153.      */
  1154.     if (hostID > 0) {
  1155.     first = hostID;
  1156.     last = hostID;
  1157.     }
  1158.  
  1159.     if (delete != -1) {
  1160.     result = DeleteRouteByID(delete);
  1161.     if (result != SUCCESS) {
  1162.         fprintf(stderr, "netroute: failed to delete routes.\n");
  1163.         exit(1);
  1164.     } else {
  1165.         printf("netroute: routes deleted.\n");
  1166.     }
  1167.     print = FALSE;
  1168.     }
  1169.  
  1170.     if (install) {
  1171.     ManageFavorings();
  1172.     if (etherString != NULL || ultraString != NULL || fddiString != NULL) {
  1173.         result = EstablishRouteScratch(hostID);
  1174.     } else {
  1175.         result = EstablishRoutesRange(-1, -1);
  1176.     }
  1177.     if (result != SUCCESS) {
  1178.         fprintf(stderr, "netroute: failed installing routes.\n");
  1179.         exit(1);
  1180.     } else {
  1181.         printf("netroute: routes installed.\n");
  1182.     }
  1183.     print = FALSE;
  1184.     }
  1185.  
  1186.     if (print) {
  1187.     (void) PrintRoutes();
  1188.     }
  1189.     exit(0);
  1190. }    
  1191.